package se.study.thread;

/**
 * @Author: tiger
 * @Date:2018/5/10
 * @Description:线程学习 注意：
 * <p>
 * 1、启动线程是调用 start() 方法，而不是 调用 run() 方法。
 * 　解析：run()方法:在本线程内调用run()方法，和其他方法没有什么区别，可以重复多次调用；
 * 　　　　start()方法:启动一个线程，实际上还是调用该Runnable对象的run()方法。
 * 　　　　打开 Thread 类的源码，start()方法里面有一句：
 * 　　　　private native void start0();  //native 关键字：本地程序调用
 * 　　　　native关键字指的是Java本地接口调用，即是使用Java调用本地操作系统的函数功能完成一些特殊的操作，而这样的代码开发在Java中几乎很少出现，因为Java的最大特点是可移植性，如果一个程序 只能在固定的操作系统上使用，那么可移植性就将彻底丧失，多线程的实现一定需要操作系统的支持，那么start0()方法实际上就和抽象方法很类似，没有方法体，而是交给JVM 去实现，即在windows下的JVM可能使用A方法实现start0()，在linux下的JVM可能使用B方法实现start0()，在调用时并不会关心具体是何方式实现了start0()方法，只会关心最终的操作结果，交给 JVM去匹配了不同的操作系统。
 * 2、不能多次启动同一个线程，即多次调用 start() 方法，只能调用一次，否则报错：
 */
public class ThreadStudy {
    public static void main(String[] args) {
        int end = 5;
        for (int i = 0; i < end; i++) {
            System.out.println("main thread ..." + i);

            if (i == 2) {
                ThreadTest thread = new ThreadTest();
                thread.start();
            }

            if (i == 3) {
                Thread thread = new Thread(new RunnableTest());
                thread.start();
            }
        }

        for (int i = 0; i < end; i++) {
            // 创建线程方法二：使用匿名内部类创建线程
            System.out.println("main thread ..." + i);
            if (i == 4) {
                new Thread(() -> {
                    for (int j = 0; j < 3; j++) {
                        System.out.println("inner class thread...");
                    }
                }).start();
            }
        }
    }


    /**
     * 创建线程方法二：实现 Runnable 接口
     * <p>
     * 1、Runnable接口应由任何类实现，其实例将由线程执行。 该类必须定义一个无参数的方法，称为run 。
     * 2、该接口旨在为希望在活动时执行代码的对象提供一个通用协议。此类整个只有一个 run() 抽象方法
     * <p>
     * 步骤：1、定义一个线程类 A 实现于 java.lang.Runnable 接口（注意：A类不是线程类,没有 start()方法，不能直接 new A 的实例启动线程）
     * 　　　2、在 A 类中覆盖 Runnable 接口的 run() 方法
     * 　　　3、在 run() 方法中编写需要执行的操作
     * 　　　4、在 main 方法（线程）中，创建线程对象，并启动线程
     * 　　　　　　创建线程类：Thread t = new Thread( new A类() ) ；
     * 　　　　　　调用 start() 方法启动线程：t.start();
     */
    static class RunnableTest implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println("RunnableTest thread ...");
            }
        }
    }

    /**
     * 创建线程方法一：继承Thread类
     * <p>
     * 步骤：1、定义一个线程类 A 继承于 java.lang.Thread 类
     * 　　　2、在 A 类中覆盖 Thread 类的 run() 方法
     * 　　　3、在 run() 方法中编写需要执行的操作
     * 　　　4、在 main 方法（线程）中，创建线程对象，并启动线程
     * 　　　　　　创建线程类：A类 a = new A()类；
     * 　　　　　　调用 start() 方法启动线程：a.start();
     */
    static class ThreadTest extends Thread {

        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println("ThreadTest thread ...");
            }
        }
    }
}
